const { hash, compare } = require("bcrypt");
const svgCaptcha = require("svg-captcha");
const { Base64 } = require("js-base64");
const { ObjectId } = require("mongodb");
const jwt = require("jsonwebtoken");
const config = require("../config/config.default");

// 检查用户名是否存在
const checkUsernameExist = async (ctx, username) => {
  // 查询数据库
  const userList = ctx.mongoClient.db().collection("users");
  const result = await userList.findOne({ username });
  return !!result;
};

// 注册
const doRegister = async (ctx, userInfo) => {
  const { username, nickname, password } = userInfo;
  // 检查用户名是否存在
  const isExist = await checkUsernameExist(ctx, username);
  if (isExist) {
    return ctx.throw({ code: 10001, message: "用户名已存在" });
  }

  // 密码加密
  const hashedPassword = await hash(password, 10);

  // 存入数据库
  const userList = ctx.mongoClient.db().collection("users");
  const result = await userList.insertOne({
    username,
    nickname,
    password: hashedPassword,
    avatar: "",
    createdAt: new Date().getTime(),
    updatedAt: new Date().getTime(),
  });

  return !!result.insertedId;
};

// 验证码
const generateCaptcha = async (ctx) => {
  const captcha = svgCaptcha.create();

  const coll = ctx.mongoClient.db().collection("captcha");
  const result = await coll.insertOne({
    text: captcha.text,
    createdAt: new Date(),
  });

  return {
    key: result.insertedId,
    svg: `data:image/svg+xml;base64,${Base64.encode(captcha.data)}`,
  };
};

// 登录
const doLogin = async (ctx, loginInfo) => {
  const { username, password, captchaCode, captchaKey } = loginInfo;
  // 查询数据库
  const catpColl = ctx.mongoClient.db().collection("captcha");
  const captcha = await catpColl.findOne({
    _id: new ObjectId(captchaKey),
    text: captchaCode,
  });
  if (!captcha) {
    return ctx.throw({ code: 10002, message: "验证码已过期，请重新获取" });
  }

  if (captcha.text.toUpperCase() !== captchaCode.toUpperCase()) {
    return ctx.throw({ code: 10003, message: "验证码错误" });
  }

  const user = await ctx.mongoClient
    .db()
    .collection("users")
    .findOne({ username });
  if (!user) {
    return ctx.throw({ code: 10004, message: "用户名不存在" });
  }

  if (!(await compare(password, user.password))) {
    return ctx.throw({ code: 10005, message: "密码错误" });
  }

  // 生成token
  const token = jwt.sign(
    {
      sub: user._id.toString(), // 用户id
      username: user.username,
    },
    config.jwt.secret,
    {
      expiresIn: "7d", // 过期时间
    }
  );

  return token;
};

module.exports = {
  doRegister,
  generateCaptcha,
  doLogin,
};
